package com.meida.bpm.provider.controller;

import com.meida.bpm.provider.common.BaseFlowableController;
import com.meida.bpm.provider.constant.FlowableConstant;
import com.meida.bpm.provider.handler.CommentListHandler;
import com.meida.bpm.provider.handler.ProcInsListHandler;
import com.meida.bpm.provider.model.ProcessInstanceDetailResponse;
import com.meida.bpm.provider.model.ProcessInstanceQueryVo;
import com.meida.bpm.provider.model.ProcessInstanceRequest;
import com.meida.bpm.provider.service.ProcessInstanceService;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.security.OpenHelper;
import com.meida.common.base.utils.FlymeUtils;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.impl.HistoricProcessInstanceQueryProperty;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 流程实例控制器
 */
@RestController
@RequestMapping("/bpm/processInstance")
public class ProcessInstanceController extends BaseFlowableController {


    @Autowired
    private ProcessInstanceService processInstanceService;


    private static Map<String, QueryProperty> allowedSortProperties = new HashMap<>();

    static {
        allowedSortProperties.put(FlowableConstant.ID, HistoricProcessInstanceQueryProperty.PROCESS_INSTANCE_ID_);
        allowedSortProperties.put(FlowableConstant.PROCESS_DEFINITION_ID, HistoricProcessInstanceQueryProperty.PROCESS_DEFINITION_ID);
        allowedSortProperties.put(FlowableConstant.PROCESS_DEFINITION_KEY, HistoricProcessInstanceQueryProperty.PROCESS_DEFINITION_KEY);
        allowedSortProperties.put(FlowableConstant.BUSINESS_KEY, HistoricProcessInstanceQueryProperty.BUSINESS_KEY);
        allowedSortProperties.put("startTime", HistoricProcessInstanceQueryProperty.START_TIME);
        allowedSortProperties.put("endTime", HistoricProcessInstanceQueryProperty.END_TIME);
        allowedSortProperties.put("duration", HistoricProcessInstanceQueryProperty.DURATION);
        allowedSortProperties.put(FlowableConstant.TENANT_ID, HistoricProcessInstanceQueryProperty.TENANT_ID);
    }

    /**
     * 流程实例列表
     *
     * @param params
     * @return
     */
    @GetMapping(value = "/page")
    public ResultBody page(@RequestParam(required = false) Map params) {
        EntityMap entityMap = new EntityMap(params);
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
        //流程实例ID
        String id = entityMap.get(FlowableConstant.PROCESS_INSTANCE_ID);
        //流程实例名称
        String insName = entityMap.get(FlowableConstant.PROCESS_INSTANCE_NAME);
        //流程定义名称
        String defName = entityMap.get(FlowableConstant.PROCESS_DEFINITION_NAME);
        //启动人
        String startedBy = entityMap.get(FlowableConstant.STARTED_BY);
        //完成状态
        Boolean isFinished = entityMap.getBoolean(FlowableConstant.FINISHED);
        if (FlymeUtils.isNotEmpty(id)) {
            query.processInstanceId(id);
        }
        if (FlymeUtils.isNotEmpty(insName)) {
            query.processInstanceNameLike(FlymeUtils.convertToLike(insName));
        }

        if (FlymeUtils.isNotEmpty(defName)) {
            query.processDefinitionName(FlymeUtils.convertToLike(defName));
        }

        if (FlymeUtils.isNotEmpty(startedBy)) {
            query.startedBy(startedBy);
        }
   /*     // ccToMe 抄送我
        if (FlymeUtils.isNotEmptyAfterTrim(params.get(FlowableConstant.CC_TO_ME))) {
            boolean ccToMe = FlymeUtils.convertToBoolean(params.get(FlowableConstant.CC_TO_ME));
            if (ccToMe) {
                query.involvedUser(OpenHelper.getUserId().toString(), FlowableConstant.CC);
            }
        }*/
        if (FlymeUtils.isNotEmpty(isFinished)) {
            if (isFinished) {
                query.finished();
            } else {
                query.unfinished();
            }
        }
        return this.pageList(entityMap, query, ProcInsListHandler.class, allowedSortProperties, HistoricProcessInstanceQueryProperty.START_TIME);

    }

    /**
     * 我的流程实例
     *
     * @param requestParams
     * @return
     */
    @GetMapping(value = "/listMyInvolved")
    public ResultBody listMyInvolved(@RequestParam EntityMap requestParams) {
        requestParams.put(FlowableConstant.INVOLVED_USER, OpenHelper.getStrUserId());
        return page(requestParams);
    }

    @GetMapping(value = "/listMyInvolvedSummary")
    public ResultBody listMyInvolvedSummary(ProcessInstanceQueryVo processInstanceQueryVo) {
        return ResultBody.ok(this.processInstanceService.listMyInvolvedSummary(processInstanceQueryVo,OpenHelper.getStrUserId()));
    }

    @GetMapping(value = "/listStartByMe")
    public ResultBody listStartByMe(@RequestParam Map<String, String> requestParams) {
        requestParams.put(FlowableConstant.START_BY_ME, OpenHelper.getStrUserId());
        return page(requestParams);
    }

    @GetMapping(value = "/listCcToMe")
    public ResultBody listCcToMe(@RequestParam Map<String, String> requestParams) {
        requestParams.put(FlowableConstant.CC_TO_ME, "true");
        return page(requestParams);
    }

    /**
     * 查询流程实例定义
     *
     * @param processInstanceId
     * @return
     */
    @GetMapping(value = "/queryById")
    public ResultBody queryById(@RequestParam String processInstanceId) {
        permissionService.validateReadPermissionOnProcessInstance(OpenHelper.getStrUserId(), processInstanceId);
        ProcessInstance processInstance = null;
        HistoricProcessInstance historicProcessInstance = processInstanceService.getHistoricProcessInstanceById(processInstanceId);
        if (historicProcessInstance.getEndTime() == null) {
            processInstance = processInstanceService.getProcessInstanceById(processInstanceId);
        }
        ProcessInstanceDetailResponse pidr = responseFactory.createProcessInstanceDetailResponse(historicProcessInstance, processInstance);
        return ResultBody.ok(pidr);
    }

    /**
     * 启动流程实例
     *
     * @param processInstanceRequest
     * @return
     */
    @PostMapping(value = "/start")
    @Transactional(rollbackFor = Exception.class)
    public ResultBody start(@RequestBody ProcessInstanceRequest processInstanceRequest) {
        processInstanceService.start(processInstanceRequest);
        return ResultBody.ok();
    }

    /**
     * 删除流程实例
     *
     * @param ids
     * @param cascade
     * @param deleteReason
     * @return
     */
    @PostMapping(value = "/delete")
    public ResultBody delete(@RequestParam String ids, @RequestParam(required = false) boolean cascade,
                             @RequestParam(required = false) String deleteReason) {
        processInstanceService.delete(ids, cascade, deleteReason);
        return ResultBody.ok();
    }

    /**
     * 挂起流程实例
     *
     * @param processInstanceRequest
     * @return
     */
    @PutMapping(value = "/suspend")
    public ResultBody suspend(@RequestBody ProcessInstanceRequest processInstanceRequest) {
        processInstanceService.suspend(processInstanceRequest.getProcessInstanceId());
        return ResultBody.ok();
    }

    /**
     * 激活流程实例
     *
     * @param processInstanceRequest
     * @return
     */
    @PutMapping(value = "/activate")
    public ResultBody activate(@RequestBody ProcessInstanceRequest processInstanceRequest) {
        processInstanceService.activate(processInstanceRequest.getProcessInstanceId());
        return ResultBody.ok();
    }

    /**
     * 查询流程实例审批意见
     *
     * @param processInstanceId
     * @return
     */
    @GetMapping(value = "/comments")
    public ResultBody comments(@RequestParam String processInstanceId) {
        permissionService.validateReadPermissionOnProcessInstance(OpenHelper.getStrUserId(), processInstanceId);
        List<Comment> list = taskService.getProcessInstanceComments(processInstanceId);
        Collections.reverse(list);
        return ResultBody.ok(this.getInterceptor(CommentListHandler.class, list));
    }

    /**
     * 表单数据
     *
     * @param processInstanceId
     * @return
     */
    @GetMapping(value = "/formData")
    public ResultBody formData(@RequestParam String processInstanceId) {
        HistoricProcessInstance processInstance = permissionService.validateReadPermissionOnProcessInstance(OpenHelper.getStrUserId(), processInstanceId);
        Object renderedStartForm = formService.getRenderedStartForm(processInstance.getProcessDefinitionId());
        Map<String, Object> variables = null;
        if (processInstance.getEndTime() == null) {
            variables = runtimeService.getVariables(processInstanceId);
        } else {
            List<HistoricVariableInstance> hisVals = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
            variables = new HashMap<>(16);
            for (HistoricVariableInstance variableInstance : hisVals) {
                variables.put(variableInstance.getVariableName(), variableInstance.getValue());
            }
        }
        Map<String, Object> ret = new HashMap<String, Object>(4);
        boolean showBusinessKey = isShowBusinessKey(processInstance.getProcessDefinitionId());
        ret.put("showBusinessKey", showBusinessKey);
        ret.put(FlowableConstant.BUSINESS_KEY, processInstance.getBusinessKey());
        ret.put("renderedStartForm", renderedStartForm);
        ret.put("variables", variables);
        return ResultBody.ok(ret);
    }

}
